MSG_LOGIN=1
MSG_KEEPALIVE=101
MSG_PROXYCOMMAND=102
MSG_UPDATEUSERLIST=201
MSG_RECEIVEDMESSAGE=202
MSG_AGENTLOGIN=2
MSG_PROXYTOCHATSERVERS=301
MSG_PROXYTOPHPSERVERS=401

ERROR_CODE_SUCCESS=0
ERROR_RESPONSE="{\"ecode\":3}"

EVENT_CONNECTED=1
EVENT_RECEIVED_DATA=2

JSON_MSG_ID_GAME_START=400

TEST_CLIENT_KEY="123456789"


-- CJson install
cjson = require "cjson"
cjson2 = cjson.new()
cjson_safe = require "cjson.safe"

-- constants
CHAT_SERVER_INTERNAL_ADDRESS="127.0.0.1:7658"
CHAT_SERVER_EXTERNAL_ADDRESS="192.168.20.129:7657"

ROOM_ID=1

TEST_USER_ID=3
-- global variables
current_user_id=1
current_step = 1
max_test_step = 1000

agent1={id=1}

-- arg functions
function clientConnect(args)
	common.warnlog("args._inarg: " .. args._inarg)
	networking.connect(args._inarg)
end

function clientLogin(arg)
	local timestamp = os.time()
	local larg = {Uid=arg._inarg.id, Rid=ROOM_ID, Timestamp=timestamp}
	local b = false
	b,larg.Sign = common.md5(larg.Uid .. larg.Rid .. larg.Timestamp .. TEST_CLIENT_KEY)
	if b then
		common.warnlog("To login")
		networking.request(MSG_LOGIN, cjson.encode(larg))
	else
		common.warnlog("common.md5 failed")
	end
end

function proxyToPhpServer(arg)
	local larg = {Cmd="Test", Value="1000"}
	networking.request(MSG_PROXYCOMMAND, cjson.encode(larg))
end

-- test step defines
test_steps = {
	[10] = {name="client1 connect", func=clientConnect, arg=CHAT_SERVER_EXTERNAL_ADDRESS, next=20},
	[20] = {name="client1 login", check={event=EVENT_CONNECTED}, func=clientLogin, arg={id=TEST_USER_ID}, next=30},
	[30] = {name="proxyToPhpServer", check={event=EVENT_RECEIVED_DATA, msgId=MSG_LOGIN}, 
			func=proxyToPhpServer, arg={Mid=JSON_MSG_ID_GAME_START}, next=40},
	[40] = {name="Finish", check={event=EVENT_RECEIVED_DATA, msgId=MSG_PROXYCOMMAND}, 
			next=1000},
}

-- initialize test case
function init()
	print("init client")
	common.dumplog("test common.dumplog")
	common.warnlog("test common.warnlog")
	common.dumplog("test cjson")
	value = {Cmd="test",From={Type="User",Id=12345},To={Type="Room",Id=321},Data={Type="OpenChat",Msg="Test message.\n\tNew line start with table"}}
	text = cjson.encode(value)
	common.dumplog("text is: " .. text)
	newvalue = cjson.decode(text)
	common.dumplog("newvalue.Cmd = " .. newvalue.Cmd)
	common.dumplog("type(newvalue.From.Id) = " .. type(newvalue.From.Id))
	newvalue.newMember = "newMember string"
	common.dumplog("newvalue.newMember = " .. newvalue.newMember)

	
	emptyValue = {}
	emptyValueText = cjson.encode(emptyValue)
	common.dumplog("empty value text is: " .. emptyValueText)
	emptyValueNew = cjson.decode(emptyValueText)
	common.dumplog("type(emptyValueNew) is " .. type(emptyValueNew))
--	emptyValueNew.newMember = "emptyValueNew string"
--	common.dumplog("emptyValueNew.newMember = " .. emptyValueNew.newMember)
	
	common.dumplog("newvalue")
end

function deepcopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

function call_test_func(func, arg)
	if type(arg) == "function" then
		func(arg())
	else
		func(arg)
	end
end

function do_test(pargs)
	args = nil
	pargsType = type(pargs)
	if pargsType == "string" then
		common.dumplog("do_test(" .. jsonargs .. ")")
		emptyValue = {}
		emptyValueText = cjson.encode(emptyValue)
		common.dumplog("empty value text is: " .. emptyValueText)
		args = cjson.decode(emptyValueText)
		if args == nil then
			common.dumplog("args is nil")
			args={}
		else
			common.dumplog("args isn't nil")
		end
		common.dumplog("type(args):" .. type(args))
		common.dumplog("0")
		args.test = "test"
		common.dumplog("1")
		args._inarg1 = 123
		common.dumplog("2")
		args._inarg = test_steps[10].arg	
		common.dumplog("3")
--		args = cjson.decode("{}")
	elseif pargsType == "table" then
		args = pargs
	elseif pargsType == nil then
		args = {}
	else
		args = {param = pargs}
	end
	
	local step = test_steps[current_step]
	local ret = 0
	local retData = ""
	while step == nil do
		current_step = current_step + 1
		if current_step > max_test_step then
			common.dumplog("test finished")
			return 0
		end
		step = test_steps[current_step]
	end
	
	common.dumplog("step[" .. current_step .. "] - " .. step.name .. " begin")
	if step.check ~= nil then
		common.dumplog("    checking")
		if step.check.event ~= nil then
			if step.check.event == args._event then
				common.dumplog("    check[Event] pass")
			else
				common.warnlog("    check[Event] failed")
			end
		end
		if step.check.msgId ~= nil then
			if step.check.msgId == args.msgId then
				common.dumplog("    check[msgId] pass")
			else
				common.warnlog("    check[msgId] failed")
				common.warnlog("        EXPECT: " .. step.check.msgId)
				if args.msgId ~= nil then
					common.warnlog("        ACTUAL: " .. args.msgId)
				else
					common.warnlog("        ACTUAL: nil")
				end

			end
		end
		if step.check.ecode ~= nil then
			-- Todo: parse json
		end
	end
	
	if step.func ~= nil then
		if step.arg ~= nil then
			if args ~= nil then
				args._inarg = step.arg	
			else
				args = {_inarg=step.arg}
			end
		end
		call_test_func(step.func, args)
		common.dumplog("    processing")
	end
	
	if step.next == nil or step.next >= max_test_step then
		common.dumplog("test case finished")
	else
		common.dumplog("step[" .. current_step .. "] - " .. step.name .. " end")
		current_step = step.next
	end
	return ret, retData
end

function start_test()
	common.dumplog("start test")
	current_step = 1
	local args = {_event=EVENT_START}
	do_test(args)
end	

function received_packet(args)
	common.dumplog("received_packet() msgId: " .. args.msgId)
	args._event=EVENT_RECEIVED_DATA
	local ret, locat retData = do_test(args)
	if ret then
		return ret, retData
	else
		return ret, ERROR_RESPONSE
	end
end

function on_connected(args)
	local connId = args.connId
	common.dumplog("on_connected[" .. connId .. "]");
	do_test({_event=EVENT_CONNECTED})
	return true, error_code_success
end	

init()